﻿using Microsoft.Xna.Framework;
using SomeGame.Zones;

namespace SomeGame {

	public class Camera {

		private const float ZOOM_UPPER_LIMIT = 10.0f;
		private const float ZOOM_LOWER_LIMIT = 1f; // TODO: Allowing this to be smaller than one (pull back) seems problematic.

		private readonly int ViewportHeight;
		private readonly int ViewportWidth;
		private int WorldHeight;
		private int WorldWidth;

		private Vector2 position;
		public Vector2 Position {
			get { return position; }
			set {
                /*
                 * Currently this is set by the Player's position. It follows the player.
                 * In the future there will be a system-controlled camera.
                 */
				float leftBarrier = ViewportWidth * .5f / zoom;             // todo: optimize. Only on ZOOM change.
				float rightBarrier = WorldWidth-ViewportWidth * .5f / zoom; // todo: optimize
				float topBarrier = WorldHeight-ViewportHeight * .5f / zoom; // todo: optimize
				float bottomBarrier = ViewportHeight * .5f / zoom;          // todo: optimize
				Vector2 tempPosition = value;
				if(tempPosition.X < leftBarrier) {
					tempPosition.X = leftBarrier;
				} else if(tempPosition.X > rightBarrier) {
					tempPosition.X = rightBarrier;
				}
				if(tempPosition.Y < bottomBarrier) {
					tempPosition.Y = bottomBarrier;
				} else if(tempPosition.Y > topBarrier) {
					tempPosition.Y = topBarrier;
				}
			    PositionDelta = tempPosition-position;
				position = tempPosition;
			}
		}

	    public Vector2 PositionDelta;

		private float zoom;
		public float Zoom {
			get { return zoom; }
			set {
				zoom = value;
				if(zoom < ZOOM_LOWER_LIMIT) {
					zoom = ZOOM_LOWER_LIMIT;
				} else if(zoom > ZOOM_UPPER_LIMIT) {
					zoom = ZOOM_UPPER_LIMIT;
				}
			}
		}

	    private CameraMode mode;
	    public CameraMode Mode {
	        get { return mode; }
            set {
                mode = value;
                if (mode == CameraMode.Menu) {
                    WorldWidth = ViewportWidth;
                    WorldHeight = ViewportHeight;
                    Zoom = 1;
                    Position = new Vector2(ViewportWidth*0.5f, ViewportHeight*0.5f);
                    IsFollowingPlayer = false;
                } else {
                    Position = GameEngine.Player.Body.Position;
                    WorldWidth = ZoneManager.CurrentZone.Bounds.Width;
                    WorldHeight = ZoneManager.CurrentZone.Bounds.Height;
                }
            }
	    }
	    public bool IsFollowingPlayer;

        public Camera(Rectangle gameBounds) {
			ViewportWidth = gameBounds.Width;
			ViewportHeight = gameBounds.Height;
            Mode = CameraMode.Menu;
        }

		public Matrix GetTransformation() {
			Matrix Transform = Matrix.CreateTranslation(new Vector3(-position.X, -position.Y, 0)) * // todo: add rotation back in?
						       Matrix.CreateScale(new Vector3(Zoom, Zoom, 1)) * 
						       Matrix.CreateTranslation(new Vector3(ViewportWidth * 0.5f, ViewportHeight * 0.5f, 0));
			return Transform;
		}

	}

    public enum CameraMode {

        Play,
        Menu

    }

}